#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'walkingsky'

from datetime import datetime,timedelta
import requests
import re
from models.db_sqlite import FundSqlite
import demjson,json
from datetime import datetime
import time
import os
from .efinance.stock.config import EastmoneyHeaders 
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
from .efinance.stock.config import STOCK_SAVE_DIR

# 创建 Session 对象
session = requests.Session()

# 配置重试策略
retries = Retry(
    total=6,                  # 总重试次数
    backoff_factor=1,         # 退避因子（每次重试等待时间递增）
    status_forcelist=[500, 502, 503, 504],  # 需要重试的状态码
    allowed_methods=frozenset(['GET'])  # 允许重试的请求方法
)
# 为 HTTP 和 HTTPS 请求设置适配器
session.mount('http://', HTTPAdapter(max_retries=retries))
session.mount('https://', HTTPAdapter(max_retries=retries))

class StockService:

    def __init__(self):
        self.db = FundSqlite('../test.db')
        self.connect_timeout = 10
        self.read_timeout = 20 
        self.max_retries= 6
        self.cache_dir = os.path.join( STOCK_SAVE_DIR,'cache')
        
    
    def get_stock_by_code(self,code):
        '''
            获取股票的是实时信息
            #code 参数，code 可以是一个，也可以是用逗号分隔的多个。 要带上市场简写，比如 sh600036,sz300301
        '''
        base_url = 'http://hq.sinajs.cn/list='
        res = session.get(base_url+code,headers=EastmoneyHeaders,
                           timeout=(self.connect_timeout,self.read_timeout))
        result = {}
        if(res.status_code == 200):
            #print(res.text)
            rows = re.findall(r'([szh\d]+)=("[^"]*")',res.text)
            #print(rows)
            for row in rows:
                text = re.findall(r'"([^"]*)"',row[1])[0]
                #print(text)
                values = text.split(',')
                if len(values) > 2:
                    #0：”飞利信”，股票名字；1：”4.320″，今日开盘价；2：”4.320″，昨日收盘价；3：”4.430″，当前价格；4：”4.470″，今日最高价；
                    # 5：”4.320″，今日最低价；6：”4.420″，竞买价，即“买一”报价；7：”4.430″，竞卖价，即“卖一”报价；
                    # 8：”22114263″，成交的股票数，由于股票交易以一百股为基本单位，所以在使用时，通常把该值除以一百；9：”589824680″，成交金额，单位为“元”，为了一目了然，通常以“万元”为成交金额的单位，所以通常把该值除以一万；
                    # 10：”4695″，“买一”申请4695股，即47手；11：”26.91″，“买一”报价；12：”57590″，“买二”13：”26.90″，“买二”14：”14700″，“买三”
                    # 15：”26.89″，“买三”16：”14300″，“买四”17：”26.88″，“买四”18：”15100″，“买五”19：”26.87″，“买五”
                    # 20：”3100″，“卖一”申报3100股，即31手；21：”26.92″，“卖一”报价
                    # (22, 23), (24, 25), (26,27), (28, 29)分别为“卖二”至“卖四的情况”30：”2020-04-30″，日期；31：”15:05:32″，时间；
                    result[row[0]] =  values
                    #for val in values:
                    #    print(val)
                else:
                    result[row[0]] =  []
            return result                
        else:
            return False

    def stock_fluctuate(self,stock,threshold=0.03):
        '''
            作废的函数
        '''
        old_price = float(stock['o_price'])
        now_price = float(stock['n_price'])
        now = datetime.strftime(datetime.now(),"%m-%d")
        float_v = (now_price - old_price)/old_price
        if (float_v >= threshold ) or (float_v < 0 and float_v <= (-threshold)):
            if float_v > 0 :
                done = 1
            else:
                done = -1

            #sql = "SELECT * FROM stock_fluctuate_watch WHERE stock_code='"+ stock['code'] + "' AND time = '"+ now +"' AND done = 1 AND threshold ="+str(threshold)
            # 一天记录一次，并且区分方向
            sql = "SELECT * FROM stock_fluctuate_watch WHERE stock_code='"+ stock['code'] + "' AND time = '"+ now +"' AND done = "+done+" AND threshold ="+str(threshold)
            res = self.db.run_sql(sql)
            #print(res)
            if len(res) == 0 :
                #now = datetime.strftime(datetime.now(),"%m-%d %H:%M")
                sql = "INSERT INTO stock_fluctuate_watch VALUES ('"+ stock['code'] +"','"+ now+ "',"+done+","+str(threshold)+");"
                res = self.db.run_sql(sql)
                #print(res)
                if float_v >= threshold:
                    return 1
                else:
                    return -1
            else:
                return 0
        else:
            return 0
        
    def get_board_lists(self):
        '''
        获取股票行业板块数据
        '''
        cache_file = os.path.join(self.cache_dir,'board_list.json')
        if os.path.exists(cache_file) and not self.is_file_older_than_days(cache_file) :
            print('使用缓存数据')
            with open (cache_file,'r',encoding='utf-8') as f:
                res_json = json.load(f)
                return res_json
        else:
            t = time.time()

            url = 'https://25.push2.eastmoney.com/api/qt/clist/get?cb=jQuery1124024989898153620205_'+str(int(round(t*1000)))+\
                '&pn=1&pz=100&po=1&np=1&fltt=2&invt=2&dect=1&wbp2u=|0|0|0|web&fid=f3&fs=m:90+t:2+f:!50'+\
                '&fields=f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f12,f13,f14,f15,f16,f17,f18,f20,f21,f23,f24,f25,f26,f22,f33,f11,f62,f128,f136,f115,f152,f124,f107,f104,f105,f140,f141,f207,f208,f209,f222'+\
                '&_='+str(int(t))
            res = session.get(url,headers=EastmoneyHeaders,
                            timeout=(self.connect_timeout,self.read_timeout))
            #print(res.text)
            res.encoding='utf-8'
            res_str = re.findall('\(([^)]+)\)',res.text)
            #print(res_str[0])
            res_json = demjson.decode(res_str[0])
            try:
                with open (cache_file,'w',encoding='utf-8') as f:
                    json.dump(res_json,f,ensure_ascii=False)
            except Exception as e:
                print(e)
            return res_json
        

    def get_board_details(self,board_code:str):
        '''
        获取股票行业板块内的详细股票信息
        返回json
        '''
        cache_file = os.path.join(self.cache_dir,board_code+'_details.json')
        if not self.is_file_older_than_days(cache_file):
            print('使用缓存数据')
            with open (cache_file,'r',encoding='utf-8') as f:
                res_json = json.load(f)
                return res_json
        else:
            t = time.time()
            url = 'https://push2.eastmoney.com/api/qt/clist/get?cb=jQuery1123046241830261769046_'+str(int(round(t*1000)))+\
                '&fid=f3&po=1&pz=100&pn=1&np=1&fltt=2&invt=2'+\
                '&fs=b:'+board_code+\
                '&fields=f12,f14,f2,f3,f62,f184,f66,f69,f72,f75,f78,f81,f84,f87,f204,f205,f124,f1,f13'+\
                '&_='+str(int(t))
            
            res = session.get(url,headers=EastmoneyHeaders,
                            timeout=(self.connect_timeout,self.read_timeout))
            #print(res.text)
            res.encoding='utf-8'
            res_str = re.findall('\(([^)]+)\)',res.text)
            #print(res_str[0])
            res_json = demjson.decode(res_str[0])
            try:
                with open (cache_file,'w',encoding='utf-8') as f:
                    json.dump(res_json,f,ensure_ascii=False)
            except Exception as e:
                print(e)
            return res_json
    
    def get_board_stocks(self,board_code:str,page=1):
        '''
        获取股票行业板块内的股票列表信息,只返回股票代码信息
        '''
        cache_file = os.path.join(self.cache_dir,board_code+'.json')
        if page == 1 and not self.is_file_older_than_days(cache_file):
            print('使用缓存数据')
            with open (cache_file,'r',encoding='utf-8') as f:
                res_json = json.load(f)
                return res_json
        else:
            t = time.time()
            url = 'https://push2.eastmoney.com/api/qt/clist/get?'+\
                'fields=f13,f12,f14'+\
                '&fid=f62&po=1&pz=100&pn=' + str(page) + '&np=1&fltt=2&invt=2'+\
                '&fs=b:'+board_code+\
                '&ut=fa5fd1943c7b386f172d6893dbfba10b'+\
                '&cb=jQuery1123030419556655289925_'+str(int(round(t*1000))) + '&_='+str(int(t))
            res = session.get(url,headers=EastmoneyHeaders,
                            timeout=(self.connect_timeout,self.read_timeout))
            #print(res.text)
            res.encoding='utf-8'
            res_str = re.findall('\(([^)]+)\)',res.text)
            #print(res_str[0])
            res_json = demjson.decode(res_str[0])
            # 如果是获取后面页面的数据，则合并数据
            if page > 1:
                try:
                    with open (cache_file,'r',encoding='utf-8') as f:
                        existing_data = json.load(f)
                except:
                    print('打开上一页的json数据文件错误')
                    existing_data = {}
                merge_json = self.merge_json_data(existing_data,res_json)
            else:
                merge_json = res_json
            try:

                with open (cache_file,'w',encoding='utf-8') as f:
                    json.dump(merge_json,f,ensure_ascii=False)
            except Exception as e:
                print(e)
            # 判断是否还有下一页的数据
            total = res_json.get('data').get('total')
            if total > 100*page:
                # 有下一页的数据
                page = page + 1
                time.sleep(2)
                self.get_board_stocks(board_code,page)
            return merge_json


    def is_file_older_than_days(self,file_path, days=30):
        """
        判断文件的修改时间是大于指定天数
        
        参数:
        file_path (str): 文件的完整路径
        days (int): 指定的天数，默认为30天
        
        返回:
        bool: 如果文件修改时间超过指定天数返回Ture，否则返回False
        """
        try:
            # 获取文件的修改时间戳
            modification_time = os.path.getmtime(file_path)
            
            # 将时间戳转换为datetime对象
            modification_datetime = datetime.fromtimestamp(modification_time)
            
            # 计算当前时间减去指定天数后的日期
            threshold_date = datetime.now() - timedelta(days=days)
            #threshold_date = datetime.now() - timedelta(seconds=days)
            
            # 判断文件修改时间是否早于阈值日期
            return modification_datetime < threshold_date
        except FileNotFoundError:
            print(f"错误: 文件 '{file_path}' 不存在")
            return True
        except Exception as e:
            print(f"错误: 检查文件时间时发生异常: {e}")
            return True
        

    def merge_json_data(self,json1, json2):
        # 创建深拷贝以避免修改原始数据
        merged = json1.copy()
        
        # 合并diff列表
        merged_diff = json1['data']['diff'] + json2['data']['diff']
        
        # 更新合并后的数据
        merged['data'] = json1['data'].copy()
        merged['data']['diff'] = merged_diff
        merged['data']['total'] = len(merged_diff)
        
        # 可以选择保留其中一个的元数据，这里保留json1的
        merged['rt'] = json1['rt']
        merged['svr'] = json1['svr']
        merged['lt'] = json1['lt']
        merged['full'] = json1['full']
        
        return merged
    
    







    
    




